{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "[WARNING  | root               ]: Supported flash-attn versions are >= 2.1.1, <= 2.6.3. Found flash-attn 2.7.4.post1.\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "3.2.0\n"
     ]
    }
   ],
   "source": [
    "import torch\n",
    "import triton\n",
    "import triton.language as tl\n",
    "from copy import deepcopy\n",
    "import os\n",
    "os.environ['TRITON_PRINT_AUTOTUNING'] = '1'\n",
    "from fp8_kernel import act_quant_block, Fp8Linear, weight_quant_block, fp8_matmul_wo_quant\n",
    "# deepseekv3 官方kernel\n",
    "from offical_kernel import act_quant\n",
    "import os\n",
    "try:\n",
    "    import transformer_engine.pytorch as te\n",
    "    from transformer_engine.common import recipe\n",
    "    HAVE_TE = True\n",
    "except:\n",
    "    HAVE_TE = False\n",
    "    print('transformer engine is not installed')\n",
    "print(triton.__version__)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- 以下测试均使用H800\n",
    "- A100系列显卡，硬件不支持fp8，只有软件支持，无法跑出下面的结果\n",
    "- triton请务必使用3.2.0，3.1.0也跑不出下面的结果"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 激活值量化\n",
    "- 对activation按块进行量化，比官方的会快些"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "True\n",
      "True\n"
     ]
    }
   ],
   "source": [
    "dtype = torch.bfloat16\n",
    "# A100系列用e5m2\n",
    "fp8_dtype = torch.float8_e4m3fn\n",
    "device = 'cuda'\n",
    "bias = False\n",
    "bs, seq_len, d = 8, 4096, 4096\n",
    "x = torch.randn(bs, seq_len, d, dtype=dtype, device=device)\n",
    "y1, s1 = act_quant(x)\n",
    "y2, s2 = act_quant_block(x, dtype=fp8_dtype)\n",
    "print(torch.allclose(y1.to(torch.float32), y2.to(torch.float32)))\n",
    "print(torch.allclose(s1.to(torch.float32), s2.to(torch.float32)))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "fp8 quant:\n",
      "       dim         my     offical\n",
      "0    128.0   7.747984   15.359689\n",
      "1    256.0   9.187445   25.183005\n",
      "2    384.0  11.552305   35.129812\n",
      "3    512.0  13.409155   45.260500\n",
      "4    640.0  16.161809   55.177853\n",
      "5    768.0  17.287217   64.951800\n",
      "6    896.0  18.798193   74.753605\n",
      "7   1024.0  20.123187   84.748372\n",
      "8   1152.0  22.525398   94.552226\n",
      "9   1280.0  23.690591  104.337350\n",
      "10  1408.0  25.260704  114.236459\n",
      "11  1536.0  27.511584  124.267057\n",
      "12  1664.0  28.716566  134.008661\n",
      "13  1792.0  30.420434  143.872276\n",
      "14  1920.0  32.194570  153.782949\n",
      "15  2048.0  33.361338  163.462862\n",
      "16  2176.0  35.943750  173.471242\n",
      "17  2304.0  37.263945  183.442831\n",
      "18  2432.0  38.309503  192.978188\n",
      "19  2560.0  39.773703  202.909410\n",
      "20  2688.0  41.787986  212.941095\n",
      "21  2816.0  43.379698  222.958356\n",
      "22  2944.0  45.486253  232.774854\n",
      "23  3072.0  46.562269  242.219046\n",
      "24  3200.0  48.360914  252.303809\n",
      "25  3328.0  50.147306  262.381494\n",
      "26  3456.0  52.226957  272.212267\n",
      "27  3584.0  53.674541  282.057106\n",
      "28  3712.0  55.008117  291.736275\n",
      "29  3840.0  56.735601  301.848948\n",
      "30  3968.0  58.604799  311.351448\n",
      "31  4096.0  59.968118  321.447343\n"
     ]
    }
   ],
   "source": [
    "torch.cuda.empty_cache()\n",
    "@triton.testing.perf_report(\n",
    "    triton.testing.Benchmark(\n",
    "        x_names=['dim'],  # argument names to use as an x-axis for the plot\n",
    "        x_vals=[128 * i for i in range(1, 32+1, 1)],  # different possible values for `x_name`\n",
    "        line_arg='provider',  # argument name whose value corresponds to a different line in the plot\n",
    "        line_vals=['my', 'offical'],  # possible values for `line_arg``\n",
    "        line_names=[\n",
    "            \"my\",\n",
    "            \"offical\",\n",
    "        ],  # label name for the lines\n",
    "        styles=[('blue', '-'), ('green', '-')],  # line styles\n",
    "        ylabel=\"ms\",  # label name for the y-axis\n",
    "        plot_name=\"fp8 quant\",  # name for the plot. Used also as a file name for saving the plot.\n",
    "        args={'bs': 4, 'seq_len': 4096}\n",
    "    ))\n",
    "def benchmark(bs, seq_len, dim, provider):\n",
    "    device = torch.device('cuda')\n",
    "    dtype = torch.bfloat16\n",
    "    device = 'cuda'\n",
    "    x = torch.randn(bs, seq_len, dim).to(device).to(dtype)\n",
    "    stream = torch.cuda.Stream()\n",
    "    torch.cuda.set_stream(stream)\n",
    "    if provider == 'my':\n",
    "        ms = triton.testing.do_bench(lambda: act_quant_block(x))\n",
    "    if provider == 'offical':\n",
    "        ms = triton.testing.do_bench(lambda: act_quant(x))\n",
    "    return ms * 1e3\n",
    "benchmark.run(show_plots=True, print_data=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# fp8矩阵乘法\n",
    "- deepseek v3的fp模式 vs torch bf16的精度"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "================================================================================ forward error: \n",
      "tensor(0.1172, device='cuda:0', dtype=torch.bfloat16, grad_fn=<MaxBackward1>) tensor(0.0167, device='cuda:0', dtype=torch.bfloat16, grad_fn=<MeanBackward0>)\n",
      "tensor([[ 0.5234,  0.2188, -0.9258,  ..., -0.7031,  0.1187, -0.8906],\n",
      "        [-0.2100, -0.2910,  1.0547,  ...,  0.0304,  0.7383,  0.2578],\n",
      "        [-0.8125,  0.2773,  0.7500,  ...,  0.5430, -0.7969, -0.1064],\n",
      "        ...,\n",
      "        [-0.1973, -0.4395, -0.0942,  ..., -0.3164,  0.5820,  0.0938],\n",
      "        [-0.1621,  0.5547,  0.5078,  ...,  0.3223, -0.4199,  0.3184],\n",
      "        [ 0.2031, -0.1758,  0.6094,  ...,  0.7539,  0.5859, -0.1729]],\n",
      "       device='cuda:0', dtype=torch.bfloat16, grad_fn=<SelectBackward0>)\n",
      "tensor([[ 0.4902,  0.2012, -0.9180,  ..., -0.7305,  0.1328, -0.8828],\n",
      "        [-0.2061, -0.2500,  1.0625,  ..., -0.0066,  0.6953,  0.2754],\n",
      "        [-0.7969,  0.2656,  0.7734,  ...,  0.5430, -0.7734, -0.1045],\n",
      "        ...,\n",
      "        [-0.1982, -0.4590, -0.1201,  ..., -0.3086,  0.5547,  0.1338],\n",
      "        [-0.1709,  0.5938,  0.4863,  ...,  0.3047, -0.4141,  0.2949],\n",
      "        [ 0.2148, -0.1523,  0.5898,  ...,  0.7695,  0.6016, -0.1582]],\n",
      "       device='cuda:0', dtype=torch.bfloat16, grad_fn=<SelectBackward0>)\n",
      "\n",
      "\n",
      "================================================================================ backward error: \n",
      "================================================================================ input grad: \n",
      "tensor(0.0669, device='cuda:0', dtype=torch.bfloat16) tensor(0.0095, device='cuda:0', dtype=torch.bfloat16)\n",
      "tensor([[ 0.4023, -0.3535,  0.3281,  ...,  0.0962,  0.0356, -0.5000],\n",
      "        [ 0.1245, -0.1855,  0.6445,  ..., -0.2754, -0.0635, -0.4512],\n",
      "        [-0.0664, -0.3926,  0.4824,  ...,  0.0299,  0.2539, -0.2080],\n",
      "        ...,\n",
      "        [ 0.3184, -0.1309,  0.3242,  ...,  0.1387,  0.2285, -0.5820],\n",
      "        [ 0.6211, -0.4414,  0.4258,  ..., -0.0723,  0.2432, -0.1787],\n",
      "        [ 0.4961, -0.3242,  0.3066,  ...,  0.2793,  0.2373, -0.5703]],\n",
      "       device='cuda:0', dtype=torch.bfloat16)\n",
      "tensor([[ 0.4043, -0.3574,  0.3164,  ...,  0.0771,  0.0159, -0.5195],\n",
      "        [ 0.1221, -0.1670,  0.6328,  ..., -0.2832, -0.0835, -0.4473],\n",
      "        [-0.0767, -0.3887,  0.4668,  ...,  0.0332,  0.2100, -0.1943],\n",
      "        ...,\n",
      "        [ 0.3145, -0.1328,  0.3281,  ...,  0.1357,  0.2217, -0.5859],\n",
      "        [ 0.6172, -0.4395,  0.4062,  ..., -0.0757,  0.2412, -0.1602],\n",
      "        [ 0.4883, -0.3340,  0.3008,  ...,  0.2754,  0.2217, -0.5703]],\n",
      "       device='cuda:0', dtype=torch.bfloat16)\n",
      "\n",
      "\n",
      "================================================================================ weight grad: \n",
      "tensor(14., device='cuda:0', dtype=torch.bfloat16) tensor(2.1094, device='cuda:0', dtype=torch.bfloat16)\n",
      "tensor([[ 15.5000,  49.5000,  12.6250,  ..., 146.0000,  20.2500, -76.0000],\n",
      "        [-20.0000,  18.3750,  54.2500,  ...,  69.5000, 104.5000,   1.3594],\n",
      "        [-35.7500,   1.6484,  64.0000,  ..., 121.5000,  73.0000, -59.7500],\n",
      "        ...,\n",
      "        [ 46.7500, -21.6250, -10.5000,  ...,  99.5000, -10.9375, -58.7500],\n",
      "        [-40.2500,  44.7500,  30.1250,  ..., 137.0000,  71.0000, -30.2500],\n",
      "        [ 68.5000, -73.5000, -46.5000,  ...,  66.5000,  30.2500, -62.5000]],\n",
      "       device='cuda:0', dtype=torch.bfloat16)\n",
      "tensor([[ 15.4375,  54.0000,  14.0625,  ..., 149.0000,  20.1250, -74.5000],\n",
      "        [-19.6250,  20.5000,  53.7500,  ...,  74.5000,  99.5000,   5.7188],\n",
      "        [-33.7500,   5.3438,  67.0000,  ..., 124.5000,  76.0000, -60.2500],\n",
      "        ...,\n",
      "        [ 47.5000, -21.5000,  -6.4375,  ..., 105.0000,  -9.0625, -58.5000],\n",
      "        [-42.7500,  53.2500,  27.7500,  ..., 143.0000,  72.5000, -28.6250],\n",
      "        [ 68.0000, -73.0000, -46.2500,  ...,  68.0000,  28.8750, -60.0000]],\n",
      "       device='cuda:0', dtype=torch.bfloat16)\n",
      "\n",
      "\n",
      "================================================================================ bias grad: \n",
      "True\n"
     ]
    }
   ],
   "source": [
    "dtype = torch.bfloat16\n",
    "fp8_dtype = torch.float8_e4m3fn\n",
    "device = 'cuda'\n",
    "bias = True\n",
    "bs, seq_len, d = 4,4096, 4096\n",
    "x1 = torch.randn(bs, seq_len, d, dtype=dtype, device=device)\n",
    "x1.requires_grad_(True)\n",
    "x2 = deepcopy(x1)\n",
    "fc1 = torch.nn.Linear(d, d, bias=bias, device=device, dtype=dtype)\n",
    "fc2 = Fp8Linear(d, d, bias=bias, device=device, dtype=dtype, fp8_dtype=fp8_dtype)\n",
    "fc2.weight.data.copy_(fc1.weight.data)\n",
    "if bias:\n",
    "    fc2.bias.data.copy_(fc1.bias.data)\n",
    "# mlp = Fp8MLP(1024, 2048).to(device).to(dtype)\n",
    "qx, sx = act_quant_block(x1, dtype=fp8_dtype)\n",
    "qw, sw = weight_quant_block(fc1.weight.data, dtype=fp8_dtype)\n",
    "y1 = fc1(x1)\n",
    "y2 = fc2(x2)\n",
    "dy = torch.rand_like(y1)\n",
    "y1.backward(dy)\n",
    "y2.backward(dy)\n",
    "print('='*80 + ' forward error: ')\n",
    "print((y1-y2).abs().max(), (y1-y2).abs().mean())\n",
    "print(y1[0])\n",
    "print(y2[0])\n",
    "print('\\n')\n",
    "print('='*80 + ' backward error: ')\n",
    "print('='*80 + ' input grad: ')\n",
    "print((x1.grad-x2.grad).abs().max(), (x1.grad-x2.grad).abs().mean())\n",
    "print(x1.grad[0])\n",
    "print(x2.grad[0])\n",
    "print('\\n')\n",
    "print('='*80 + ' weight grad: ')\n",
    "# 这个东西会在bs*seq_len进行累加，导致误差会很大，但是乘上学习率，比如1e-3，就会把这个误差进行缩小。或者bs设置为1，seq_len设置为128，也会小一些\n",
    "print((fc1.weight.grad-fc2.weight.grad).abs().max(), (fc1.weight.grad-fc2.weight.grad).abs().mean())\n",
    "print(fc1.weight.grad)\n",
    "print(fc2.weight.grad)\n",
    "print('\\n')\n",
    "print('='*80 + ' bias grad: ')\n",
    "print(torch.allclose(fc1.bias.grad, fc2.bias.grad))\n",
    "# e4m3的精度还可以，e5m2差的基本翻倍"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## forward"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- 下面对比了torch bf16 vs 3种fp8\n",
    "- 分别是te的fp8（delay的量化方式），deepseek-v3的fp8（online的量化方式）以及纯fp8（无量化）\n",
    "- delay的量化方式，就是输出的值是未知的，通过历史值去预测一个scale值，并且是一般是tensor级别的量化，可以理解为，在无量化的基础上，对最终结果乘上一个scale factor（一般是个标量）\n",
    "- online的量化是计算x和w的scale值，对每个中间的累加结果都进行量化乘上scale factor（一般是个向量或者矩阵），然后进行累加\n",
    "- 因此简单分析下，就知道下面的benchmark结果为什么是这样了\n",
    "- 反正通过我自己的实验结果，单纯使用triton实现deepseekv3那种fp8，总体上是不如原生bf16的（效率差不多，效果差），可能使用cuda去实现，也许可以"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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mlRWVoaxY8fCw8MDQUFB+Oyzz1Ttd39kZjAYsGrVKrzwwgtwd3dH165dkZqaivPnz2Po0KFo0aIFBg4ciAsXLjRxJUTUFBiIiEiTEhISkJKSgh07dmD//v04dOgQjh8/ft/3LFiwAGPHjkVmZibCwsLw1ltv4d1338Xs2bORnp4OEcHUqVObqAIiakr8yIyINKe0tBSrV6/G+vXrMWzYMADAunXr0KZNm/u+b/z48XjjjTcAADNnzoTFYsHcuXMRHR0NAIiLi8P48eMbd/BE5BC8QkREmnPhwgVUVlYiMjJS2deqVSt06dLlvu/r2bOn8tpkMgEAwsPDVftu374Nq9X6iEdMRI7GQEREdIeLi4vy2mAw3HOfzWZr2oERUaNjICIizenQoQNcXFyQlpam7Lt58ybOnj3rwFER0eOM9xARkeZ4eHhg4sSJSEhIgK+vLwICAjBnzhw4OfH/gETUMAYiItKkxYsXo7S0FCNHjkTLli0xffp0FBcXO3pYRPSYMoiIOHoQRERERI7E68dERESkewxEREREpHsMRERERKR7DERERESkewxEREREpHsMRERERKR7DERERESkewxEREREpHsMRERERKR7DERERESkewxEREREpHv/A/ZoKoM0BAMfAAAAAElFTkSuQmCC",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "fp8:\n",
      "       dim  with-quant-fp8      te-fp8   torch-bf16  without-quant-fp8\n",
      "0    512.0      130.206510  230.112270    16.051019          12.200175\n",
      "1   1024.0      130.428448  228.037849    32.627385          23.616003\n",
      "2   1536.0      130.785748  224.168032    63.660324          39.754029\n",
      "3   2048.0      130.553246  225.071758   104.807831          60.940940\n",
      "4   2560.0      176.199347  230.645373   156.819329          88.898420\n",
      "5   3072.0      237.708986  235.191122   224.237636         125.718772\n",
      "6   3584.0      316.220015  247.239068   298.119694         173.072472\n",
      "7   4096.0      403.212637  277.791589   391.188204         223.910049\n",
      "8   4608.0      525.971770  345.744967   512.444377         273.262143\n",
      "9   5120.0      623.636246  410.754889   616.778016         348.405868\n",
      "10  5632.0      791.490793  484.761506   778.581083         426.526099\n",
      "11  6144.0      883.410752  562.595665   904.311597         482.725561\n",
      "12  6656.0     1079.687834  668.924630  1084.922433         575.216174\n",
      "13  7168.0     1231.031179  757.481873  1273.223877         678.270221\n",
      "14  7680.0     1435.953259  846.758902  1411.657929         789.067566\n",
      "15  8192.0     1577.313542  926.821470  1620.830894         876.380742\n"
     ]
    }
   ],
   "source": [
    "torch.cuda.empty_cache()\n",
    "@triton.testing.perf_report(\n",
    "    triton.testing.Benchmark(\n",
    "        x_names=['dim'],  # argument names to use as an x-axis for the plot\n",
    "        x_vals=[256 * i for i in range(2, 32+2, 2)],  # different possible values for `x_name`\n",
    "        line_arg='provider',  # argument name whose value corresponds to a different line in the plot\n",
    "        line_vals=['with-quant-fp8', 'te-fp8', 'torch', 'without-quant-fp8'],  # possible values for `line_arg``\n",
    "        line_names=[\n",
    "            \"with-quant-fp8\",\n",
    "            \"te-fp8\",\n",
    "            'torch-bf16',\n",
    "            'without-quant-fp8'\n",
    "        ],  # label name for the lines\n",
    "        styles=[('blue', '-'), ('green', '-'), ('orange', '-'), ('red', '-')],  # line styles\n",
    "        ylabel=\"ms\",  # label name for the y-axis\n",
    "        plot_name=\"fp8\",  # name for the plot. Used also as a file name for saving the plot.\n",
    "        args={'bs': 4, 'seq_len': 2048}\n",
    "    ))\n",
    "def benchmark(bs, seq_len, dim, provider):\n",
    "    device = torch.device('cuda')\n",
    "    dtype = torch.bfloat16\n",
    "    device = 'cuda'\n",
    "    x = torch.randn(bs, seq_len, dim).to(device).to(dtype)\n",
    "    stream = torch.cuda.Stream()\n",
    "    torch.cuda.set_stream(stream)\n",
    "    if provider == 'with-quant-fp8':\n",
    "        fc = Fp8Linear(dim, dim, bias=False).to(dtype).to(device)\n",
    "        ms = triton.testing.do_bench(lambda: fc(x))\n",
    "\n",
    "    if provider == 'without-quant-fp8':\n",
    "        fc = Fp8Linear(dim, dim, bias=False).to(dtype).to(device)\n",
    "        a = x.view(-1, x.size(-1)).to(torch.float8_e5m2)\n",
    "        b = fc.weight.to(torch.float8_e5m2)\n",
    "        ms = triton.testing.do_bench(lambda: fp8_matmul_wo_quant(a,b))\n",
    "\n",
    "    if provider == 'te-fp8':\n",
    "        if HAVE_TE:\n",
    "            fc = te.Linear(dim, dim, bias=False).to(dtype).to(device)\n",
    "            # Create an FP8 recipe. Note: All input args are optional.\n",
    "            fp8_recipe = recipe.DelayedScaling(margin=0, fp8_format=recipe.Format.E4M3)\n",
    "            def func():\n",
    "                with te.fp8_autocast(enabled=True, fp8_recipe=fp8_recipe):\n",
    "                    out = fc(x)\n",
    "                return out\n",
    "            ms = triton.testing.do_bench(lambda: func())\n",
    "        else:\n",
    "            ms = 100\n",
    "            \n",
    "    if provider == 'torch':\n",
    "        fc = torch.nn.Linear(dim, dim, bias=False).to(dtype).to(device)\n",
    "        ms = triton.testing.do_bench(lambda: fc(x))\n",
    "\n",
    "    return ms * 1e3\n",
    "benchmark.run(show_plots=True, print_data=True)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## backward\n",
    "- 去除无量化的和te-fp8（没法单拿出来进行backward）"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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nZrhuDGGfv36kT9/foKCgqhduzY7duzI0ObkyZM0b96c0NBQcubMSZs2bUhMTMzQZv369dSoUYPAwEAKFSrE4MGDb/WpZTBw4EDuuececuTIQXh4OA0aNGDbtm0Z2pw/f5727duTJ08eQkJCaNiwIUeOHMnQZt++fdStW5fg4GDCw8Pp0aMHaWlpGdosXryYu+++m4CAAEqWLMmoUaNu9ellMHz4cCpWrOiaxCwqKorZs2e7jnvLeV5q0KBBOBwOOnfu7NrnLec6YMAAHA5HhkeZMmVcx73lPC84ePAgLVq0IE+ePAQFBVGhQgXWrFnjOu4Nv5eKFi162WfqcDho37494F2faXp6On379qVYsWIEBQVRokQJ3n777QzrgnnDZ+pixCP9/PPP5vXXXzc//fSTAcyUKVMyHB80aJAJCwszU6dONevWrTNPP/20KVasmElKSnK1eeKJJ0ylSpXMihUrzG+//WZKlixpmjVr5joeHx9vIiIiTPPmzc3GjRvNhAkTTFBQkPnqq69u12ma6OhoM3LkSLNx40YTGxtrnnzySVO4cGGTmJjoatOuXTtTqFAhs2DBArNmzRpz3333mfvvv991PC0tzZQvX97Url3b/Pnnn+bnn382efPmNX369HG12b17twkODjZdu3Y1mzdvNp999pnx9fU1c+bMuW3nOn36dDNr1iyzfft2s23bNvPaa68ZPz8/s3HjRq86z4utWrXKFC1a1FSsWNF06tTJtd9bzrV///7mrrvuMocPH3Y9jh075nXnaYwxJ0+eNEWKFDGtW7c2K1euNLt37zZz5841O3fudLXxht9LR48ezfB5zp8/3wBm0aJFxhjv+kzfffddkydPHjNz5kyzZ88eM3nyZBMSEmKGDh3qauMNn+kFCkRe4NJA5HQ6TWRkpPnggw9c+06fPm0CAgLMhAkTjDHGbN682QBm9erVrjazZ882DofDHDx40BhjzBdffGFy5cplkpOTXW169eplSpcufYvP6J8dPXrUAGbJkiXGGOu8/Pz8zOTJk11ttmzZYgCzfPlyY4wVHn18fExcXJyrzfDhw01oaKjr3Hr27GnuuuuuDD+rSZMmJjo6+laf0lXlypXLfPvtt155nmfOnDGlSpUy8+fPNw8//LArEHnTufbv399UqlTpise86TyNsX43PPjgg/943Ft/L3Xq1MmUKFHCOJ1Or/tM69ata1588cUM+5599lnTvHlzY4z3faa6ZeaF9uzZQ1xcHLVr13btCwsLo3r16ixfvhyA5cuXkzNnTqpVq+ZqU7t2bXx8fFi5cqWrzUMPPYS/v7+rTXR0NNu2bePUqVO36Wwyio+PByB37twArF27ltTU1AznWqZMGQoXLpzhXCtUqEBERISrTXR0NAkJCWzatMnV5uL3uNDmwnvcbunp6UycOJGzZ88SFRXllefZvn176tate1k93nauO3bsoECBAhQvXpzmzZuzb98+wPvOc/r06VSrVo3GjRsTHh5OlSpV+Oabb1zHvfH3UkpKCt999x0vvvgiDofD6z7T+++/nwULFrB9+3YA1q1bx9KlS6lTpw7gfZ+pApEXiouLA8jwD+7C9oVjcXFxhIeHZzieLVs2cufOnaHNld7j4p9xOzmdTjp37swDDzxA+fLlXXX4+/uTM2fODG0vPdd/O49/apOQkEBSUtKtOJ0r2rBhAyEhIQQEBNCuXTumTJlCuXLlvO48J06cyB9//MHAgQMvO+ZN51q9enVGjRrFnDlzGD58OHv27KFGjRqcOXPGq84TYPfu3QwfPpxSpUoxd+5cXnnlFf7zn/8wevToDPV60++lqVOncvr0aVq3bu36+d70mfbu3ZumTZtSpkwZ/Pz8qFKlCp07d6Z58+YZ6vWWz1Sr3YvHaN++PRs3bmTp0qV2l3LLlC5dmtjYWOLj4/nhhx+IiYlhyZIldpeVqfbv30+nTp2YP38+gYGBdpdzS134P2mAihUrUr16dYoUKcL3339PUFCQjZVlPqfTSbVq1XjvvfcAqFKlChs3buTLL78kJibG5upujf/+97/UqVOHAgUK2F3KLfH9998zbtw4xo8fz1133UVsbCydO3emQIECXvmZ6gqRF4qMjAS4bGTDkSNHXMciIyM5evRohuNpaWmcPHkyQ5srvcfFP+N26dChAzNnzmTRokUULFjQtT8yMpKUlBROnz6dof2l5/pv5/FPbUJDQ2/rF5e/vz8lS5akatWqDBw4kEqVKjF06FCvOs+1a9dy9OhR7r77brJly0a2bNlYsmQJn376KdmyZSMiIsJrzvVSOXPm5M4772Tnzp1e9ZkC5M+fn3LlymXYV7ZsWdctQm/7vfTXX3/xyy+/0LZtW9c+b/tMe/To4bpKVKFCBVq2bEmXLl1cV3a97TNVIPJCxYoVIzIykgULFrj2JSQksHLlSqKiogCIiori9OnTrF271tVm4cKFOJ1Oqlev7mrz66+/kpqa6mozf/58SpcuTa5cuW7LuRhj6NChA1OmTGHhwoUUK1Ysw/GqVavi5+eX4Vy3bdvGvn37Mpzrhg0bMvyjnD9/PqGhoa5f4FFRURne40KbC+9hF6fTSXJysledZ61atdiwYQOxsbGuR7Vq1WjevLnrubec66USExPZtWsX+fPn96rPFOCBBx64bEqM7du3U6RIEcC7fi8BjBw5kvDwcOrWreva522f6blz5/DxyRgTfH19cTqdgPd9phpl5qHOnDlj/vzzT/Pnn38awHz88cfmzz//NH/99ZcxxhoKmTNnTjNt2jSzfv16U79+/SsOhaxSpYpZuXKlWbp0qSlVqlSGoZCnT582ERERpmXLlmbjxo1m4sSJJjg4+LYOhXzllVdMWFiYWbx4cYahrufOnXO1adeunSlcuLBZuHChWbNmjYmKijJRUVGu4xeGuT7++OMmNjbWzJkzx+TLl++Kw1x79OhhtmzZYj7//PPbPsy1d+/eZsmSJWbPnj1m/fr1pnfv3sbhcJh58+Z51XleycWjzIzxnnPt1q2bWbx4sdmzZ49ZtmyZqV27tsmbN685evSoV52nMdYUCtmyZTPvvvuu2bFjhxk3bpwJDg423333nauNt/xeSk9PN4ULFza9evW67Jg3faYxMTHmjjvucA27/+mnn0zevHlNz549XW285TM1RsPuPdaiRYsMcNkjJibGGGMNh+zbt6+JiIgwAQEBplatWmbbtm0Z3uPEiROmWbNmJiQkxISGhpoXXnjBnDlzJkObdevWmQcffNAEBASYO+64wwwaNOh2naIxxlzxHAEzcuRIV5ukpCTz6quvmly5cpng4GDzzDPPmMOHD2d4n71795o6deqYoKAgkzdvXtOtWzeTmpqaoc2iRYtM5cqVjb+/vylevHiGn3E7vPjii6ZIkSLG39/f5MuXz9SqVcsVhozxnvO8kksDkbeca5MmTUz+/PmNv7+/ueOOO0yTJk0yzMvjLed5wYwZM0z58uVNQECAKVOmjPn6668zHPeW30tz5841wGW1G+Ndn2lCQoLp1KmTKVy4sAkMDDTFixc3r7/+eobh8d7ymRpjjMOYi6acFBEREcmC1IdIREREsjwFIhEREcnyFIhEREQky1MgEhERkSxPgUhERESyPAUiERERyfIUiERERCTLUyASERGRLE+BSESyjJo1a9K5c2cAihYtyieffGJrPSLiPrLZXYCIiB1Wr15N9uzZ7S5DRNyEApGIZEn58uWzuwQRcSO6ZSYiXuns2bO0atWKkJAQ8ufPz0cffZTh+KW3zBwOB1999RVPPfUUwcHBlC1bluXLl7Nz505q1qxJ9uzZuf/++9m1a9dtPhMRuR0UiETEK/Xo0YMlS5Ywbdo05s2bx+LFi/njjz+u+pq3336bVq1aERsbS5kyZXj++ef5v//7P/r06cOaNWswxtChQ4fbdAYicjvplpmIeJ3ExET++9//8t1331GrVi0ARo8eTcGCBa/6uhdeeIHnnnsOgF69ehEVFUXfvn2Jjo4GoFOnTrzwwgu3tngRsYWuEImI19m1axcpKSlUr17dtS937tyULl36qq+rWLGi63lERAQAFSpUyLDv/PnzJCQkZHLFImI3BSIRkf/x8/NzPXc4HP+4z+l03t7CROSWUyASEa9TokQJ/Pz8WLlypWvfqVOn2L59u41ViYg7Ux8iEfE6ISEhtGnThh49epAnTx7Cw8N5/fXX8fHR/wOKyJUpEImIV/rggw9ITEykXr165MiRg27duhEfH293WSLiphzGGGN3ESIiIiJ20vVjERERyfIUiERERCTLUyASERGRLE+BSERERLI8BSIRERHJ8hSIREREJMtTIBIREZEsT4FIREREsjwFIhEREcnyFIhEREQky1MgEhERkSzv/wH0cfyKEjK1JgAAAABJRU5ErkJggg==",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "fp8:\n",
      "       dim   triton-fp8   torch-bf16\n",
      "0    512.0   387.836367    55.357933\n",
      "1   1024.0   443.414807   102.096044\n",
      "2   1536.0   392.323613   170.854986\n",
      "3   2048.0   409.856558   237.756878\n",
      "4   2560.0   606.997192   379.071534\n",
      "5   3072.0   778.629184   521.642268\n",
      "6   3584.0   972.558975   689.696491\n",
      "7   4096.0  1224.984527   911.050022\n",
      "8   4608.0  1543.113828  1117.092490\n",
      "9   5120.0  1864.775777  1384.978414\n",
      "10  5632.0  2230.494499  1677.311420\n",
      "11  6144.0  2551.821947  1959.353685\n",
      "12  6656.0  3006.776810  2306.646585\n",
      "13  7168.0  3369.151115  2596.934557\n",
      "14  7680.0  3925.501585  3094.293594\n",
      "15  8192.0  4333.503723  3498.168468\n"
     ]
    }
   ],
   "source": [
    "torch.cuda.empty_cache()\n",
    "@triton.testing.perf_report(\n",
    "    triton.testing.Benchmark(\n",
    "        x_names=['dim'],  # argument names to use as an x-axis for the plot\n",
    "        x_vals=[256 * i for i in range(2, 32+2, 2)],  # different possible values for `x_name`\n",
    "        line_arg='provider',  # argument name whose value corresponds to a different line in the plot\n",
    "        line_vals=['triton-fp8',  'torch'],  # possible values for `line_arg``\n",
    "        line_names=[\n",
    "            \"triton-fp8\",\n",
    "            'torch-bf16',\n",
    "        ],  # label name for the lines\n",
    "        styles=[('blue', '-'), ('green', '-')],  # line styles\n",
    "        ylabel=\"ms\",  # label name for the y-axis\n",
    "        plot_name=\"fp8\",  # name for the plot. Used also as a file name for saving the plot.\n",
    "        args={'bs': 4, 'seq_len': 2048}\n",
    "    ))\n",
    "def benchmark(bs, seq_len, dim, provider):\n",
    "    device = torch.device('cuda')\n",
    "    dtype = torch.bfloat16\n",
    "    device = 'cuda'\n",
    "    x = torch.randn(bs, seq_len, dim).to(device).to(dtype)\n",
    "    x.requires_grad_(True)\n",
    "    stream = torch.cuda.Stream()\n",
    "    torch.cuda.set_stream(stream)\n",
    "    if provider == 'triton-fp8':\n",
    "        fc = Fp8Linear(dim, dim, bias=False).to(dtype).to(device)\n",
    "        y = fc(x)\n",
    "        dy = torch.randn_like(y)\n",
    "        ms = triton.testing.do_bench(lambda: y.backward(dy, retain_graph=True))\n",
    "\n",
    "    # if provider == 'te-fp8':\n",
    "    #     fc = te.Linear(dim, dim, bias=False).to(dtype).to(device)\n",
    "    #     # Create an FP8 recipe. Note: All input args are optional.\n",
    "    #     fp8_recipe = recipe.DelayedScaling(margin=0, fp8_format=recipe.Format.E4M3)\n",
    "    #     with te.fp8_autocast(enabled=True, fp8_recipe=fp8_recipe):\n",
    "    #         y = fc(x)\n",
    "    #     loss = y.sum()\n",
    "    #     loss.backward()\n",
    "    #     def func():\n",
    "    #         with te.fp8_autocast(enabled=True, fp8_recipe=fp8_recipe):\n",
    "    #             loss.backward(retain_graph=True)\n",
    "    #     ms = triton.testing.do_bench(lambda: func())\n",
    "        \n",
    "    if provider == 'torch':\n",
    "        fc = torch.nn.Linear(dim, dim, bias=False).to(dtype).to(device)\n",
    "        y = fc(x)\n",
    "        dy = torch.randn_like(y)\n",
    "        ms = triton.testing.do_bench(lambda: y.backward(dy, retain_graph=True))\n",
    "\n",
    "    return ms * 1e3\n",
    "benchmark.run(show_plots=True, print_data=True)\n",
    "# 其实两者(offical vs my)性能差异不大, 如果想快速实现，表示清楚，直接按顺序计算即可\n",
    "# dim变大之后，貌似还是torch内置的矩阵乘法更优秀\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.13"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
